package com.ioe.p2p.service;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class MsgDeal {

    static private final int PACKET_SIZE = 1024 * 64;
    static private final Map<String, String> _addressContainer = new HashMap<>();

    public static MsgDeal getMsgDeal() {
        return Instance.instance;
    }

    private static final class Instance{
        private static final MsgDeal instance = new MsgDeal();
    }

    public void init(DatagramSocket ds) {
        byte[] bytes = new byte[PACKET_SIZE];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
        try {
            for (;;){
                ds.receive(dp);
                byte[] b = new byte[dp.getLength()];
                System.arraycopy(dp.getData(), 0, b, 0, b.length);
                String text = new String(b, StandardCharsets.UTF_8);
                // 0 -> src - 1 -> obj - 2 -> content
                String[] data = text.split("-");
                int len;
                int port = dp.getPort();
                InetSocketAddress sa = (InetSocketAddress) dp.getSocketAddress();
                String hostAddress = sa.getAddress().getHostAddress();
                String g;
                String s = _addressContainer.get(g = data[0]);
                String msg = hostAddress + ";" + port;
                if (null != s && !s.equals(msg)){
                    // 更新用户地址
                    _addressContainer.put(g, msg);
                    System.out.println("用户：" + g + "，地址为：" + msg + "。更新地址信息");
                    broadcast(ds);
                }
                if ((len = data.length) == 1){
                    // 说明是刚加入 记录用户地址和名
                    _addressContainer.put(g, msg);
                    broadcast(ds);
                    System.out.println("用户：" + g + "，地址为：" + msg + "。加入聊天");
                }
                if (len == 3){
                    // 通知打洞目标 a;127.0.0.1;51417-src
                    if (text.contains(":1:")){
                        // 0 -> src - 1 -> obj - 2 -> content
                        String obj = data[1];
                        // 发送消息
                        String objAddress = _addressContainer.get(obj);
                        int length = text.length();
                        String[] split = objAddress.split(";");
                        DatagramPacket dpp = new DatagramPacket(
                                text.getBytes(StandardCharsets.UTF_8),
                                length,
                                new InetSocketAddress(split[0], Integer.parseInt(split[1]))
                        );
                        ds.send(dpp);
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void broadcast(DatagramSocket ds) throws IOException {
        // 有人加入做个播报
        for (String address : _addressContainer.values()) {
            StringBuilder sendMsg = new StringBuilder(":0:");
            _addressContainer.keySet().forEach(userName -> sendMsg.append(userName).append(";").append(_addressContainer.get(userName)).append("-"));
            int sendMsgLen;
            sendMsg.delete((sendMsgLen = sendMsg.length()) - 1, sendMsgLen);
            System.out.println("服务器发送更新用户消息：" + sendMsg);
            int length = sendMsg.length();
            String[] split = address.split(";");
            DatagramPacket dpp = new DatagramPacket(
                    sendMsg.toString().getBytes(StandardCharsets.UTF_8),
                    length,
                    new InetSocketAddress(split[0], Integer.parseInt(split[1]))
            );
            ds.send(dpp);
        }
    }
}
